package com.vvv.dca;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.vvv.dca.InvestmentData;
import com.vvv.dca.StockData;
import com.vvv.dca.StockDataDTO;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

@SpringBootApplication
public class DcaCalculatorApplication {

    static final String filePath = "E:\\google download\\比特币历史数据 (5).csv";

    static final String exportFilePath = "E:\\google download\\investment_data6.csv";

    static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    static final List<StockDataDTO> stockDataList = new ArrayList<>();

    static final List<InvestmentData> list = new ArrayList<>();

    static LocalDate startDate = LocalDate.parse("2024-05-11");

    static String interval = "w";  // 默认是每日

    static Double investment = 100d;  // 每次的投资金额

    public static void main(String[] args) {

        readBitcoinDataFromCSV();
        //inputData();
        calculator();
        export();
    }

    private static void export() {
        try {
            exportToCsv(list, exportFilePath);
            System.out.println("CSV 文件已成功导出至: " + exportFilePath);
        } catch (IOException e) {
            System.err.println("导出 CSV 失败: " + e.getMessage());
        }
    }

    private static void calculator() {
        int index = 0;
        for (int i = 0; i < stockDataList.size(); i++) {
            LocalDate date = stockDataList.get(i).getDate();
            if (date.equals(startDate)) {
                index = i;
                break;
            }
        }

        // DCA 总日期
        double preValue = 0;
        double totalInvested = 0;
        double initPrice = 0;
        double preBtcTotal = 0;

        // 记录上一次投资的日期
        LocalDate lastInvestmentDate = startDate;
        double weeklyChange = 0;  // 每周累计变化

        for (int i = index; i < stockDataList.size(); i++) {
            StockDataDTO stockDataDTO = stockDataList.get(i);
            LocalDate date = stockDataDTO.getDate();
            Double closePrice = stockDataDTO.getClosePrice();
            Double change = stockDataDTO.getChange();

            if (i == index) {
                change = 0d;
                initPrice = closePrice;
            }

            // 计算累计的周变化（对于周频率）
            if ("w".equals(interval)) {
                weeklyChange += change;
            }

            // 检查日期是否符合投资频率要求
            if (shouldInvest(lastInvestmentDate, date)) {
                totalInvested += investment;



                // 计算从开始到当前的变化
                double changeFromStart = (closePrice - initPrice) / initPrice;
                double btcValue = preValue * (1 + change) + investment;
                if ("w".equals(interval)) {
                    btcValue = preValue * (1 + weeklyChange) + investment;
                }
                double profit = btcValue - totalInvested;
                double profitPercentage = profit / totalInvested;

                double bitcoinTotal = investment / closePrice + preBtcTotal;

                InvestmentData investmentData = InvestmentData.builder()
                        .date(date)
                        .closePrice(closePrice)
                        .changePercentage(change)
                        .changeFromStart(changeFromStart)
                        .totalInvested(totalInvested)
                        .btcValue(btcValue)
                        .profit(profit)
                        .profitPercentage(profitPercentage)
                        .btcTotal(bitcoinTotal)
                        .build();
                if ("w".equals(interval)) {
                    investmentData.setChangePercentage(weeklyChange);
                }
                list.add(investmentData);

                preValue = btcValue;
                preBtcTotal = bitcoinTotal;

                // 如果是周投资，应该计算7天的累计变化
                if ("w".equals(interval)) {
                    weeklyChange = 0;  // 每次投资后重置累计变化
                }

                // 更新上一次投资日期
                lastInvestmentDate = date;
            }
        }

        list.forEach(System.out::println);
    }

    // 判断是否该按照频率进行投资
    private static boolean shouldInvest(LocalDate lastInvestmentDate, LocalDate currentDate) {
        if (lastInvestmentDate.equals(currentDate)) return true;
        switch (interval) {
            case "d":
                return true;  // 每天投资
            case "w":
                // 如果上次投资日期加上一周等于当前日期，或者当前日期大于上次投资日期加上一周，认为满足周频率投资条件
                return !lastInvestmentDate.plusWeeks(1).isAfter(currentDate);
            case "m":
                // 如果上次投资日期加上一月等于当前日期，或者当前日期大于上次投资日期加上一月，认为满足月频率投资条件
                return !lastInvestmentDate.plusMonths(1).isAfter(currentDate);
            case "y":
                // 如果上次投资日期加上一年等于当前日期，或者当前日期大于上次投资日期加上一年，认为满足年频率投资条件
                return !lastInvestmentDate.plusYears(1).isAfter(currentDate);
            default:
                return true;  // 默认每日投资
        }
    }



    public static void exportToCsv(List<InvestmentData> list, String filePath) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            // 写入表头
            writer.write("Date,Close Price,% Change,% Change From Start,Total Invested,B Value,Profit,Profit %,B Total");
            writer.newLine();

            // 日期格式化
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");

            // 写入数据行
            for (InvestmentData data : list) {
                String line = String.format("%s,%.2f,%.2f%%,%.2f%%,$%.2f,B %.8f,$%.2f,%.2f%%,B %.8f",
                        data.getDate().format(dateFormatter), // Date
                        data.getClosePrice(), // Close Price
                        data.getChangePercentage() * 100, // % Change
                        data.getChangeFromStart() * 100, // % Change From Start
                        data.getTotalInvested(), // Total Invested
                        data.getBtcValue(), // ₿ Value
                        data.getProfit(), // Profit
                        data.getProfitPercentage() * 100, // Profit %
                        data.getBtcTotal() // ₿ Total
                );
                writer.write(line);
                writer.newLine();
            }
        }
    }

    private static void inputData() {
        Scanner scanner = new Scanner(System.in);
        System.out.print("输入开始日期yyyy-MM-dd: ");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        startDate = LocalDate.parse(scanner.next(), formatter);
        System.out.print("输入dca频率,每日d,每周w,每月m,每年y: ");
        interval = scanner.next();
        System.out.print("输入dca力度,u为单位: ");
        investment = scanner.nextDouble();
    }

    private static void readBitcoinDataFromCSV() {
        // 使用 EasyExcel 读取 Excel 文件
        EasyExcel.read(filePath, StockData.class, new AnalysisEventListener<StockData>() {
            @Override
            public void invoke(StockData stockData, AnalysisContext analysisContext) {

                System.out.println(stockData);
                // 每解析一行数据时触发，将数据添加到列表
                String date = stockData.getDate();
                String closePrice = stockData.getClosePrice();
                String change = stockData.getChange();


                LocalDate date2 = LocalDate.parse(date, formatter);
                StockDataDTO stockDataDTO = StockDataDTO.builder()
                        .date(date2)
                        .closePrice(Double.parseDouble(closePrice))
                        .change(Double.parseDouble(change))
                        .build();
                stockDataList.add(stockDataDTO);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                // 解析完成后触发
                System.out.println("数据解析完成，共读取 " + stockDataList.size() + " 行数据");
            }
        }).sheet().doRead();

        stockDataList.sort((o1, o2) -> o1.getDate().compareTo(o2.getDate()));
    }
}
